package com.zxiw.zxedu.recyclerview.adapter

import android.content.Context
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener
import android.widget.AdapterView.OnItemLongClickListener
import androidx.recyclerview.widget.RecyclerView


/**
 * @author zhangxiaoming
 * @date 2023/8/18
 * @description 万能适配器（采用泛型） 主要是针对RecyclerView的适配器 <br/>
 * 1.(更加厉害)  抽取出来的模板适配器，任何适配器继承该适配器，就很容易实现适配器功能。<br/>
 * 2.支持多个item<br/>
 * 3.RecyclerView不同与AbsListView(ListView、GrideView)具有点击setOnItemClickListener事件监听
 * 故本代码中自己新增了setOnItemClickListener、setOnItemLongClickListener，来解决RecyclerView的OnItem事件
 */
abstract class BaseRecyclerViewAdapter<T> constructor(context: Context, vararg layoutIds: Int) :
    RecyclerView.Adapter<BH>() {
    var mList: MutableList<T> = mutableListOf()
    protected var mInflater: LayoutInflater
    protected var mLayoutIds: IntArray
    private val mConvertViews: SparseArray<View> = SparseArray<View>()
    private var mOnItemClickListener: OnItemClickListener<T>? = null
    private var mOnItemLongClickListener: OnItemLongClickListener<T>? = null

    init {
        mInflater = LayoutInflater.from(context)
        mLayoutIds = layoutIds
    }

    override fun getItemViewType(position: Int): Int {
        return if (position in 0 until itemCount) {
            checkLayout(mList[position], position)
        } else {
            position
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BH {
        if (viewType < 0 || viewType > mLayoutIds.size) {
            throw ArrayIndexOutOfBoundsException("checkLayout > LayoutId.length")
        }
        require(mLayoutIds.isNotEmpty()) { "not layoutId" }
        val layoutId = mLayoutIds[viewType]
        val view: View = inflateItemView(layoutId, parent)
        //因为Sticky也要用到tag,所有采用多tag的方式处理，产生一个唯一的key值
        var viewHolder: BaseRecyclerViewHolder? =
            view.getTag("holder".hashCode()) as BaseRecyclerViewHolder
        if (viewHolder == null || viewHolder.layoutId != layoutId) {
            viewHolder = createViewHolder(view, layoutId)
        }
        return viewHolder
    }

    override fun onBindViewHolder(holder: BH, position: Int, payloads: MutableList<Any>) {
        if (payloads.isEmpty()) {
            // payloads 为 空，说明是更新整个 ViewHolder
            onBindViewHolder(holder, position)
        } else {
            // payloads 不为空，这只更新需要更新的 View 即可。
            super.onBindViewHolder(holder, position, payloads)
        }
    }

    override fun onBindViewHolder(holder: BH, position: Int) {
        require(position in 0 until mList.size) { "The position must be between 0 and list size:${mList.size} position:$position" }
        val item: T = mList[position]
        // 绑定数据
        onBindData(holder, position, item)
        //绑定监听事件
        onBindItemClickListener(holder, position)
    }

    override fun getItemCount(): Int {
        return mList.size
    }

    /**
     * 绑定数据到Item View上
     * @param viewHolder
     * @param position   数据的位置
     * @param item       数据项
     */
    protected abstract fun onBindData(viewHolder: BH, position: Int, item: T)

    fun checkLayout(item: T, position: Int): Int {
        return 0
    }

    fun isEmpty(): Boolean {
        return itemCount == 0
    }

    //若果想用自定义的ViewHolder，可以进行自定义，但是必须继承自BaseRecyclerViewHolder
    protected open fun createViewHolder(view: View, layoutId: Int): BaseRecyclerViewHolder {
        return BaseRecyclerViewHolder(view, layoutId)
    }

    /**
     * 解析布局资源
     */
    protected fun inflateItemView(layoutId: Int, viewGroup: ViewGroup): View {
        return mConvertViews.get(layoutId) ?: mInflater.inflate(layoutId, viewGroup, false)
    }

    fun setOnItemClickListener(onItemClickListener: OnItemClickListener<T>) {
        mOnItemClickListener = onItemClickListener
    }

    fun setOnItemClickListener(listener: (view: View, item: T, position: Int) -> Unit) {
        mOnItemClickListener = object : OnItemClickListener<T> {
            override fun onItemClick(view: View, item: T, position: Int) {
                listener(view, item, position)
            }
        }
    }

    fun setOnItemLongClickListener(onItemLongClickListener: OnItemLongClickListener<T>) {
        mOnItemLongClickListener = onItemLongClickListener
    }

    fun setOnItemLongClickListener(listener: (view: View, item: T, position: Int) -> Unit) {
        mOnItemLongClickListener = object : OnItemLongClickListener<T> {
            override fun onItemLongClick(view: View, item: T, position: Int) {
                listener(view, item, position)
            }
        }
    }

    /**
     * 注册item点击、长按事件
     * @param holder
     * @param position
     */
    protected fun onBindItemClickListener(holder: BH, position: Int) {
        mOnItemClickListener?.let {
            holder.itemView.setOnClickListener { view ->
                it.onItemClick(view, mList[position], position)
            }
        }
        mOnItemLongClickListener?.let {
            holder.itemView.setOnLongClickListener { view ->
                it.onItemLongClick(view, mList[position], position)
                return@setOnLongClickListener true
            }
        }
    }

    interface OnItemClickListener<T> {
        fun onItemClick(view: View, item: T, position: Int)
    }

    interface OnItemLongClickListener<T> {
        fun onItemLongClick(view: View, item: T, position: Int)
    }
}